"""角色模型"""

from typing import Dict, Any, Optional, List
from enum import Enum
from pydantic import BaseModel, Field


class CharacterType(Enum):
    """角色类型"""
    PLAYER = "player"  # 玩家方
    ENEMY = "enemy"    # 敌方


class Character(BaseModel):
    """角色类"""
    
    id: str = Field(..., description="角色唯一标识")
    name: str = Field(..., description="角色名称")
    character_type: CharacterType = Field(..., description="角色类型")
    
    # 基础属性
    max_hp: int = Field(100, description="最大生命值")
    current_hp: int = Field(100, description="当前生命值")
    attack: int = Field(20, description="攻击力 - 决定伤害基础")
    defense: int = Field(10, description="防御力 - 决定减伤基础")
    speed: int = Field(15, description="速度 - 行动顺序越快越早行动")
    
    # 战斗属性
    hit_rate: int = Field(85, description="命中率 - 基础命中百分比(0-100)")
    dodge_rate: int = Field(10, description="闪避率 - 决定是否完全闪避伤害(0-100)")
    crit_rate: int = Field(5, description="暴击率 - 决定暴击概率(0-100)")
    crit_damage: int = Field(150, description="暴击伤害 - 决定暴击后伤害百分比(100+)")
    
    # 战场位置
    position_x: Optional[int] = Field(None, description="X坐标(0-3)")
    position_y: Optional[int] = Field(None, description="Y坐标(0-5)")
    
    # 状态
    is_alive: bool = Field(True, description="是否存活")
    
    # 技能相关
    skills: List[str] = Field(default_factory=list, description="角色拥有的技能ID列表")
    skill_cooldowns: Dict[str, int] = Field(default_factory=dict, description="技能冷却时间，key为技能ID，value为剩余冷却回合数")
    
    def __init__(self, **data):
        super().__init__(**data)
        if self.current_hp > self.max_hp:
            self.current_hp = self.max_hp
    
    def take_damage(self, damage: int, is_crit: bool = False, is_hit: bool = True) -> Dict[str, Any]:
        """受到伤害
        
        Args:
            damage: 基础伤害值
            is_crit: 是否暴击
            is_hit: 是否命中
            
        Returns:
            Dict包含伤害详情: {
                'actual_damage': int,  # 实际伤害
                'is_hit': bool,        # 是否命中
                'is_crit': bool,       # 是否暴击
                'is_dodged': bool      # 是否闪避
            }
        """
        result = {
            'actual_damage': 0,
            'is_hit': is_hit,
            'is_crit': is_crit,
            'is_dodged': False
        }
        
        # 如果未命中，直接返回
        if not is_hit:
            return result
        
        # 检查是否闪避（命中后的闪避检查）
        is_dodged = self.calculate_dodge_chance()
        result['is_dodged'] = is_dodged
        
        if is_dodged:
            # 闪避成功，不受伤害
            return result
        
        # 计算暴击伤害
        if is_crit:
            damage = int(damage * self.crit_damage / 100)
        
        # 计算防御减伤
        actual_damage = max(1, damage - self.defense)  # 至少造成1点伤害
        
        # 应用伤害
        self.current_hp = max(0, self.current_hp - actual_damage)
        
        if self.current_hp <= 0:
            self.is_alive = False
        
        result['actual_damage'] = actual_damage
        return result
    
    def heal(self, heal_amount: int) -> int:
        """治疗"""
        if not self.is_alive:
            return 0
            
        old_hp = self.current_hp
        self.current_hp = min(self.max_hp, self.current_hp + heal_amount)
        actual_heal = self.current_hp - old_hp
        
        return actual_heal
    
    def set_position(self, x: int, y: int) -> bool:
        """设置位置"""
        if 0 <= x <= 3 and 0 <= y <= 5:
            self.position_x = x
            self.position_y = y
            return True
        return False
    
    def get_position(self) -> tuple[Optional[int], Optional[int]]:
        """获取位置"""
        return (self.position_x, self.position_y)
    
    def calculate_hit_chance(self, target_dodge: int) -> bool:
        """计算是否命中目标
        
        Args:
            target_dodge: 目标的闪避率
            
        Returns:
            bool: 是否命中
        """
        import random
        # 命中率 - 目标闪避率 = 最终命中率
        final_hit_rate = max(5, self.hit_rate - target_dodge)  # 最低5%命中率
        return random.randint(1, 100) <= final_hit_rate
    
    def calculate_crit_chance(self) -> bool:
        """计算是否暴击
        
        Returns:
            bool: 是否暴击
        """
        import random
        return random.randint(1, 100) <= self.crit_rate
    
    def calculate_dodge_chance(self) -> bool:
        """计算是否闪避
        
        Returns:
            bool: 是否闪避
        """
        import random
        return random.randint(1, 100) <= self.dodge_rate
    
    def is_skill_available(self, skill_id: str) -> bool:
        """检查技能是否可用（不在冷却中且角色存活）
        
        Args:
            skill_id: 技能ID
            
        Returns:
            bool: 技能是否可用
        """
        # 死亡角色无法使用任何技能
        if not self.is_alive:
            return False
            
        return self.skill_cooldowns.get(skill_id, 0) <= 0
    
    def use_skill(self, skill_id: str, cooldown_turns: int) -> bool:
        """使用技能并设置冷却
        
        Args:
            skill_id: 技能ID
            cooldown_turns: 冷却回合数
            
        Returns:
            bool: 是否成功使用技能
        """
        # 死亡角色无法使用任何技能
        if not self.is_alive:
            return False
            
        if not self.is_skill_available(skill_id):
            return False
        
        self.skill_cooldowns[skill_id] = cooldown_turns
        return True
    
    def reduce_cooldowns(self):
        """减少所有技能的冷却时间（每回合调用）"""
        for skill_id in list(self.skill_cooldowns.keys()):
            if self.skill_cooldowns[skill_id] > 0:
                self.skill_cooldowns[skill_id] -= 1
            if self.skill_cooldowns[skill_id] <= 0:
                del self.skill_cooldowns[skill_id]
    
    def get_available_skills(self, all_skills: Dict[str, Any]) -> Dict[str, Any]:
        """获取当前可用的技能列表
        
        Args:
            all_skills: 所有技能的字典
            
        Returns:
            Dict: 可用的技能字典
        """
        available = {}
        for skill_id, skill in all_skills.items():
            if self.is_skill_available(skill_id):
                available[skill_id] = skill
        return available
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "id": self.id,
            "name": self.name,
            "type": self.character_type.value,
            "hp": f"{self.current_hp}/{self.max_hp}",
            "attack": self.attack,
            "defense": self.defense,
            "speed": self.speed,
            "hit_rate": self.hit_rate,
            "dodge_rate": self.dodge_rate,
            "crit_rate": self.crit_rate,
            "crit_damage": self.crit_damage,
            "position": {
                "x": self.position_x,
                "y": self.position_y
            },
            "is_alive": self.is_alive
        }